package com.cb.common.image;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;

import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGEncodeParam;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

public class ScaleImage {

	private int width;

	private int height;

	private int scaleWidth;

	private double support = (double) 3.0;

	private double PI = (double) 3.14159265358978;

	private double[] contrib;

	private double[] normContrib;

	private double[] tmpContrib;

	private int startContrib, stopContrib;

	private int nDots;

	private int nHalfDots;

	/**
	 * # * Start: Use Lanczos filter to replace the original algorithm for image
	 * # * scaling. Lanczos improves quality of the scaled image modify by
	 * :blade #
	 */
	
	
	

	public BufferedImage imageZoomOut(BufferedImage srcBufferImage, int w, int h) {
		width = srcBufferImage.getWidth();
		height = srcBufferImage.getHeight();
		height = (int)((double)w / (double)width * (double)height);
		scaleWidth = w;

		if (DetermineResultSize(w, height) == 1) {
			return srcBufferImage;
		}
		CalContrib();
		BufferedImage pbOut = HorizontalFiltering(srcBufferImage, w);
		BufferedImage pbFinalOut = VerticalFiltering(pbOut, height);
		return pbFinalOut;
	}

	/**
	 * # * 决定图像尺寸 #
	 */
	private int DetermineResultSize(int w, int h) {
		double scaleH, scaleV;
		scaleH = (double) w / (double) width;
		scaleV = (double) h / (double) height;
		// 需要判断一下scaleH，scaleV，不做放大操作
		if (scaleH >= 1.0 && scaleV >= 1.0) {
			return 1;
		}
		return 0;

	} // end of DetermineResultSize()

	private double Lanczos(int i, int inWidth, int outWidth, double Support) {
		double x;

		x = (double) i * (double) outWidth / (double) inWidth;

		return Math.sin(x * PI) / (x * PI) * Math.sin(x * PI / Support)
				/ (x * PI / Support);

	} // end of Lanczos()

	//    
	// Assumption: same horizontal and vertical scaling factor
	//    
	private void CalContrib() {
		nHalfDots = (int) ((double) width * support / (double) scaleWidth);
		nDots = nHalfDots * 2 + 1;
		try {
			contrib = new double[nDots];
			normContrib = new double[nDots];
			tmpContrib = new double[nDots];
		} catch (Exception e) {
			System.out.println("init   contrib,normContrib,tmpContrib" + e);
		}

		int center = nHalfDots;
		contrib[center] = 1.0;

		double weight = 0.0;
		int i = 0;
		for (i = 1; i <= center; i++) {
			contrib[center + i] = Lanczos(i, width, scaleWidth, support);
			weight += contrib[center + i];
		}

		for (i = center - 1; i >= 0; i--) {
			contrib[i] = contrib[center * 2 - i];
		}

		weight = weight * 2 + 1.0;

		for (i = 0; i <= center; i++) {
			normContrib[i] = contrib[i] / weight;
		}

		for (i = center + 1; i < nDots; i++) {
			normContrib[i] = normContrib[center * 2 - i];
		}
	} // end of CalContrib()

	// 处理边缘
	private void CalTempContrib(int start, int stop) {
		double weight = 0;

		int i = 0;
		for (i = start; i <= stop; i++) {
			weight += contrib[i];
		}

		for (i = start; i <= stop; i++) {
			tmpContrib[i] = contrib[i] / weight;
		}

	} // end of CalTempContrib()

	private int GetRedValue(int rgbValue) {
		int temp = rgbValue & 0x00ff0000;
		return temp >> 16;
	}

	private int GetGreenValue(int rgbValue) {
		int temp = rgbValue & 0x0000ff00;
		return temp >> 8;
	}

	private int GetBlueValue(int rgbValue) {
		return rgbValue & 0x000000ff;
	}

	private int ComRGB(int redValue, int greenValue, int blueValue) {

		return (redValue << 16) + (greenValue << 8) + blueValue;
	}

	// 行水平滤波
	private int HorizontalFilter(BufferedImage bufImg, int startX, int stopX,
			int start, int stop, int y, double[] pContrib) {
		double valueRed = 0.0;
		double valueGreen = 0.0;
		double valueBlue = 0.0;
		int valueRGB = 0;
		int i, j;

		for (i = startX, j = start; i <= stopX; i++, j++) {
			valueRGB = bufImg.getRGB(i, y);

			valueRed += GetRedValue(valueRGB) * pContrib[j];
			valueGreen += GetGreenValue(valueRGB) * pContrib[j];
			valueBlue += GetBlueValue(valueRGB) * pContrib[j];
		}

		valueRGB = ComRGB(Clip((int) valueRed), Clip((int) valueGreen),
				Clip((int) valueBlue));
		return valueRGB;

	} // end of HorizontalFilter()

	// 图片水平滤波
	private BufferedImage HorizontalFiltering(BufferedImage bufImage, int iOutW) {
		int dwInW = bufImage.getWidth();
		int dwInH = bufImage.getHeight();
		int value = 0;
		BufferedImage pbOut = new BufferedImage(iOutW, dwInH,
				BufferedImage.TYPE_INT_RGB);

		for (int x = 0; x < iOutW; x++) {

			int startX;
			int start;
			int X = (int) (((double) x) * ((double) dwInW) / ((double) iOutW) + 0.5);
			int y = 0;

			startX = X - nHalfDots;
			if (startX < 0) {
				startX = 0;
				start = nHalfDots - X;
			} else {
				start = 0;
			}

			int stop;
			int stopX = X + nHalfDots;
			if (stopX > (dwInW - 1)) {
				stopX = dwInW - 1;
				stop = nHalfDots + (dwInW - 1 - X);
			} else {
				stop = nHalfDots * 2;
			}

			if (start > 0 || stop < nDots - 1) {
				CalTempContrib(start, stop);
				for (y = 0; y < dwInH; y++) {
					value = HorizontalFilter(bufImage, startX, stopX, start,
							stop, y, tmpContrib);
					pbOut.setRGB(x, y, value);
				}
			} else {
				for (y = 0; y < dwInH; y++) {
					value = HorizontalFilter(bufImage, startX, stopX, start,
							stop, y, normContrib);
					pbOut.setRGB(x, y, value);
				}
			}
		}

		return pbOut;

	} // end of HorizontalFiltering()

	private int VerticalFilter(BufferedImage pbInImage, int startY, int stopY,
			int start, int stop, int x, double[] pContrib) {
		double valueRed = 0.0;
		double valueGreen = 0.0;
		double valueBlue = 0.0;
		int valueRGB = 0;
		int i, j;

		for (i = startY, j = start; i <= stopY; i++, j++) {
			valueRGB = pbInImage.getRGB(x, i);

			valueRed += GetRedValue(valueRGB) * pContrib[j];
			valueGreen += GetGreenValue(valueRGB) * pContrib[j];
			valueBlue += GetBlueValue(valueRGB) * pContrib[j];
			// System.out.println(valueRed+"->"+Clip((int)valueRed)+"<-");
			//    
			// System.out.println(valueGreen+"->"+Clip((int)valueGreen)+"<-");
			// System.out.println(valueBlue+"->"+Clip((int)valueBlue)+"<-"+"-->");
		}

		valueRGB = ComRGB(Clip((int) valueRed), Clip((int) valueGreen),
				Clip((int) valueBlue));
		// System.out.println(valueRGB);
		return valueRGB;

	} // end of VerticalFilter()

	private BufferedImage VerticalFiltering(BufferedImage pbImage, int iOutH) {
		int iW = pbImage.getWidth();
		int iH = pbImage.getHeight();
		int value = 0;
		BufferedImage pbOut = new BufferedImage(iW, iOutH,
				BufferedImage.TYPE_INT_RGB);

		for (int y = 0; y < iOutH; y++) {

			int startY;
			int start;
			int Y = (int) (((double) y) * ((double) iH) / ((double) iOutH) + 0.5);

			startY = Y - nHalfDots;
			if (startY < 0) {
				startY = 0;
				start = nHalfDots - Y;
			} else {
				start = 0;
			}

			int stop;
			int stopY = Y + nHalfDots;
			if (stopY > (int) (iH - 1)) {
				stopY = iH - 1;
				stop = nHalfDots + (iH - 1 - Y);
			} else {
				stop = nHalfDots * 2;
			}

			if (start > 0 || stop < nDots - 1) {
				CalTempContrib(start, stop);
				for (int x = 0; x < iW; x++) {
					value = VerticalFilter(pbImage, startY, stopY, start, stop,
							x, tmpContrib);
					pbOut.setRGB(x, y, value);
				}
			} else {
				for (int x = 0; x < iW; x++) {
					value = VerticalFilter(pbImage, startY, stopY, start, stop,
							x, normContrib);
					pbOut.setRGB(x, y, value);
				}
			}

		}

		return pbOut;

	} // end of VerticalFiltering()

	private int Clip(int x) {
		if (x < 0)
			return 0;
		if (x > 255)
			return 255;
		return x;
	}
	
	
	
	/**
     * 将多个小图片 合成一张大jpg图  (小的jpg图片 按照行列顺序平铺)
     * @param smallJPG ArrayList 一组小的jpg图片
     * @param tempPath 背景图片路径
     * @param bigWidth int 大图宽度
     * @param smallWidth int  单个文字生成的小图的宽度和高度是一致的
     * @return 
     */
	public void createBigJPG(List smallJPG,String tempPath ,int bigWidth, int smallHeigh,
			Color bgColor, String picName,String coverName) {
		try {
			
			if (bigWidth < smallHeigh) // 如果大图片 的高度比小图片 的高度还小 直接返回
				return;
			int colCount = bigWidth / 100; // 每行放置的字数
			int rowCount = smallJPG.size(); // 小图行数
			int leftMargin = (int) ((bigWidth - colCount * 100) / 2f); // 左边距
			int footMargin=30; //下边距
			int topMargin=50; //上边距
			int lineMargin=8; //图片之间间隔
			int x = leftMargin;
			int y = topMargin;
			int bigHeight=0;
			
			for (int i = 0; i < rowCount; i++) { // 遍历每行
					String jpgname = (String) (smallJPG.get(i));
					ImageIcon icon = new ImageIcon(jpgname);
					Image img = icon.getImage();
					int imgWidth = img.getHeight(null);
					bigHeight+=img.getHeight(null);
			}
			bigHeight=footMargin+topMargin+bigHeight+lineMargin;
			if(rowCount==0)bigHeight=180;
			BufferedImage bufImage = new BufferedImage(bigWidth, bigHeight,
					BufferedImage.TYPE_INT_RGB);
			Graphics2D g = bufImage.createGraphics();
			g.setColor(bgColor); // 背景的颜色
			g.fillRect(0, 0, bigWidth, bigHeight);
			ImageIcon icon1 = new ImageIcon(tempPath);
			
			icon1.setImage(icon1.getImage().getScaledInstance(bigWidth,bigHeight,Image.SCALE_DEFAULT)); 
			g.drawImage(icon1.getImage(), 0, 0, null);
			
			bigHeight=0;
			for (int i = 0; i < rowCount; i++) { // 遍历每行
				String jpgname = (String) (smallJPG.get(i));
				ImageIcon icon = new ImageIcon(jpgname);
				Image img = icon.getImage();
				int imgWidth = img.getHeight(null);
				bigHeight+=img.getHeight(null);
				g.drawImage(img, x, y, null);
				
				y =y+(bigHeight)+lineMargin;
			}
			
			
			g.dispose();
			File dirFile=new File(picName);
			if(!dirFile.exists()){
				dirFile.mkdirs();
			}
			
			FileOutputStream out = new FileOutputStream(picName+"/albumcover"+coverName+".jpg"); // 指定输出文件
			JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out); // 设置文件格式
			JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(bufImage); // 从图片
																					// 缓冲中读取
			param.setQuality(50f, true);
			encoder.encode(bufImage, param); // 存盘
			out.flush();
			out.close();
		} catch (Exception e) {
			System.out.println("createBigJPG Failed!");
			e.printStackTrace();
		}
	} 
	
	public static void main(String[] args) throws IOException {
		ArrayList smallJPG1 = new ArrayList();
		ArrayList smallJPG = new ArrayList();
		ArrayList smallJPG2 = new ArrayList();
		smallJPG2.add("d://3.jpg");
		
		//smallJPG.add("d://2.jpg");
		//smallJPG.add("d://3.jpg");
		smallJPG1.add("d://1.jpg");
		
		smallJPG1.add("d://2.jpg");
		new ScaleImage().createBigJPG(smallJPG1,"D://h3.gif",160,90,Color.white,"D://4.jpg","1");
		
		//String a[] = new String[] {"d://2.jpg","d://3.jpg"};
		///new ScaleImage().jpgToGif(a, "d://5.gif");
		/* Long star = System.currentTimeMillis();
		 ScaleImage pic = new ScaleImage();
	     pic.composePic("d://1.jpg","d://3.jpg","d:\\out_pic.gif",0,70);
	     Long end =System.currentTimeMillis();
	     System.out.print("time====:"+(end-star));*/
	}
	
	private synchronized void jpgToGif(String pic[], String newPic) {
        try {
            AnimatedGifEncoder e = new AnimatedGifEncoder();  
            e.setRepeat(0);
            e.start(newPic);
            BufferedImage src[] = new BufferedImage[pic.length];
            for (int i = 0; i < src.length; i++) {
                e.setDelay(1500); //设置播放的延迟时间
                src[i] = ImageIO.read(new File(pic[i])); // 读入需要播放的jpg文件
                e.addFrame(src[i]);  //添加到帧中
            }
            e.finish();
        } catch (Exception e) {
            System.out.println( "jpgToGif Failed:");
            e.printStackTrace();
        }
    } 
	/**
	 * End: Use Lanczos filter to replace the original algorithm for image
	 * scaling. Lanczos improves quality of the scaled image modify by :blade
	 */
	/**
    *
    * @param filesrc
    * @param logosrc
    * @param outsrc
    * @param x 位置
    * @param y 位置
    */
 public void composePic(String filesrc,String logosrc,String outsrc,int x,int y) {
   try {
       File bgfile = new File(filesrc);
       Image bg_src = javax.imageio.ImageIO.read(bgfile);
      
       File logofile = new File(logosrc);
       Image logo_src = javax.imageio.ImageIO.read(logofile);
      
       int bg_width = bg_src.getWidth(null);
       int bg_height = bg_src.getHeight(null);
       int logo_width = logo_src.getWidth(null);;
       int logo_height = logo_src.getHeight(null);

       BufferedImage tag = new BufferedImage(bg_width, bg_height, BufferedImage.TYPE_INT_RGB);
      
       Graphics2D g2d = tag.createGraphics();
       g2d.drawImage(bg_src, 0, 0, bg_width, bg_height, null);
      
       g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP,1.0f)); //透明度设置开始 
       g2d.drawImage(logo_src,x,y,logo_width,logo_height, null);           
       g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER)); //透明度设置 结束
      
       FileOutputStream out = new FileOutputStream(outsrc);
       JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
       encoder.encode(tag);
       out.close();
   }catch (Exception e) {
       e.printStackTrace();
   }
 }

 
}
